package com.resto.scm.web.service.impl;

import cn.restoplus.common.utils.ListUtil;
import cn.restoplus.common.utils.log.LogBetter;
import cn.restoplus.common.utils.log.LogLevel;
import com.resto.scm.web.dto.ArticleBomDo;
import com.resto.scm.web.manager.MdRulArticleBomHeadManager;
import com.resto.scm.web.service.ArticleSaleService;
import com.resto.shop.web.dto.ArticleSellCountDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.restoplus.common.tracelog.TraceLoggerFactory.logger;


/**
 *
 * 移动加权平均法计算公式是：
 * 移动平均单价=（本次进货的成本+原有库存的成本）/（本次进货数量+原有存货数量）
 * 本批发出存货成本=本批发出存货数量×存货当前移动平均单价
 * 菜品消耗计算
 */
@Service("articleSaleService")
public class ArticleSaleServiceImpl implements ArticleSaleService {


    @Autowired
    private MdRulArticleBomHeadManager mdRulArticleBomHeadManager;



    @Override
    public   Map<Long, Map<String, BigDecimal>> countMaterialStockSellGroupByMaterialId(String shopId, String lastCountTime) {
        //查询菜品销售，原始数据统计
        List<ArticleSellCountDto> articleSellCountDtos = mdRulArticleBomHeadManager.findArticleByLastCountTime(shopId,lastCountTime);
        Map<String, List<ArticleSellCountDto>> articleSellCountMap = articleSellCountDtos.stream().collect(Collectors.groupingBy(ArticleSellCountDto::getArticleId));
        if(ListUtil.isNotEmpty(articleSellCountDtos)){
            return countStockByMaterialId(shopId, articleSellCountDtos, articleSellCountMap);
        }
        return new HashMap<>();
    }

    private Map<Long, Map<String, BigDecimal>> countStockByMaterialId(String shopId, List<ArticleSellCountDto> articleSellCountDtos, Map<String, List<ArticleSellCountDto>> articleSellCountMap) {
        //查询bom清单,菜品维度统计单个菜品消耗原材料
        List<ArticleBomDo> articleBomDos =mdRulArticleBomHeadManager.queryBom(shopId);
        //分组
        Map<String, List<ArticleBomDo>> articleBomDoMap = articleBomDos.stream().collect(Collectors.groupingBy(ArticleBomDo::getArticleId));
        //校验并记录日志
        checkSellArticleSizeGtArticleBomSize(articleSellCountDtos, articleBomDos, articleBomDoMap);

        // 将菜品销量，扁平到具体的原料,并且以原料分组
        Map<Long, List<ArticleBomDo>> listMap = articleSellToflatMapMaterialGroupByMaterialId(articleSellCountMap, articleBomDoMap);

        Map<Long, Map<String, BigDecimal>> stockBurn = countMaterialStockBurn(listMap);


        return stockBurn ;
    }

    private Map<Long, Map<String,BigDecimal>> countMaterialStockBurn(Map<Long, List<ArticleBomDo>> listMap) {
        //4,统计同一个原料id消耗的总的数量
        Map<Long, Map<String,BigDecimal>> stockBurn = new HashMap<>();
        for (Map.Entry<Long,List<ArticleBomDo>> each:listMap.entrySet()) {
            List<ArticleBomDo> values = each.getValue();
            stockBurn.put(each.getValue().get(0).getMaterialId(),countMaterialStock(values));
        }
        return stockBurn;
    }

    private void checkSellArticleSizeGtArticleBomSize(List<ArticleSellCountDto> articleSellCountDtos, List<ArticleBomDo> articleBomDos, Map<String, List<ArticleBomDo>> articleBomDoMap) {
        if(articleSellCountDtos.size()>articleBomDos.size()){
            LogBetter.instance(logger)
                    .setLevel(LogLevel.INFO)
                    .setMsg("[SCM-菜品销售菜品种类大于新建bom清单上面的菜品种类，会引起销售的菜品没有bom清单，导致所卖的菜品，没有bom计算，引起误差]")
                    .log();
            List<String> articleIds = new ArrayList<>();
            for (ArticleSellCountDto articleSellCountDto:articleSellCountDtos) {
                if(ListUtil.isNullOrEmpty(articleBomDoMap.get(articleSellCountDto.getArticleId()))){
                    articleIds.add(articleSellCountDto.getArticleId());
                }
            }
            LogBetter.instance(logger)
                    .setLevel(LogLevel.INFO)
                    .addParm("没有设置清单的articleIds===",articleIds)
                    .log();
        }
    }

    /***
     * map<String,List<ArticleBomDo>> maps
     * 2，将maps里面的values 转化成newDo   put 到一个新的list<newDo>中 newDos
     *             newDo
     *                          ---销量
     *                          --- 原料1------规格 单位
     *                              原料2------规格 单位
     *                              原料3------规格 单位
     * 3，对newDos进行分组 groupByMaterialId
     *
     * 4,统计同一个原料id消耗的总的数量
     *
     */
    private Map<Long, List<ArticleBomDo>> articleSellToflatMapMaterialGroupByMaterialId(Map<String, List<ArticleSellCountDto>> articleSellCountMap, Map<String, List<ArticleBomDo>> articleBomDoMap) {
        // 1，将第一个map统计结束的销量   组装到第二个map中
        List<ArticleBomDo> allArticleBomDos = new ArrayList<>();
        for (Map.Entry<String, List<ArticleBomDo>>   articleSellMap:articleBomDoMap.entrySet()){
            //单个菜品所有餐盒数量
            int articleMealFeeNumber =0;
            //单个餐品所卖份数
            int articleTotalCount =0;
            List<ArticleSellCountDto> articleSellCountDtos1 = articleSellCountMap.get(articleSellMap.getKey());
            if(ListUtil.isNotEmpty(articleSellCountDtos1)){
                Assert.isTrue(articleSellCountDtos1.size()==1,"articleSellCountDtos分组后list size大小必须为1");
                articleMealFeeNumber =articleSellCountDtos1.get(0).getMealFeeNumber();
                articleTotalCount =articleSellCountDtos1.get(0).getTotalCount();
            }
            // 2,将maps里面的values 转化成newDo   put 到一个新的list<newDo>中 newDos
            List<ArticleBomDo> values = articleSellMap.getValue();
            List<ArticleBomDo> newValues = new ArrayList<>(values.size());

            for (ArticleBomDo each:values) {
                each.setArticleMealFeeNumber(articleMealFeeNumber);
                each.setArticleTotalCount(articleTotalCount);
                newValues.add(each);
            }
            allArticleBomDos.addAll(newValues);
        }
        //3,对newDos进行分组 groupByMaterialId
        return allArticleBomDos.stream().collect(Collectors.groupingBy(ArticleBomDo::getMaterialId));
    }

    private Map<String, BigDecimal> countMaterialStock(List<ArticleBomDo> values) {
        Map<String,BigDecimal> materialStockBurn = new HashMap<>(2);
        for (ArticleBomDo articleBomDo:values) {
            //TODO  需要和jack确认
            materialStockBurn.put(ArticleSaleService.materialTotalCount, BigDecimal.valueOf(articleBomDo.getArticleTotalCount()).multiply(articleBomDo.getMaterialCount()).multiply(articleBomDo.getMinMeasureUnit()));
            materialStockBurn.put(ArticleSaleService.materialMealFeeNumber,BigDecimal.valueOf(articleBomDo.getArticleMealFeeNumber()).multiply(articleBomDo.getMaterialCount()));
        }
        return materialStockBurn;
    }

}
